package zcj.stu;

import org.springframework.boot.*;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;

@Configuration
public class C39_1 {
    public static void main(String[] args) throws Exception {
        SpringApplication springApplication = new SpringApplication();
        springApplication.addListeners(event -> System.out.println(event.getClass()));
        //从springFactories中获取类
        List<String> list = SpringFactoriesLoader.loadFactoryNames(SpringApplicationRunListener.class, C39_1.class.getClassLoader());
        for (String className : list) {
            System.out.println(className);
        }
        //获得该构造器
        Constructor<?> constructor = Class.forName(list.get(0)).getConstructor(SpringApplication.class, String[].class);
        constructor.setAccessible(true);
        SpringApplicationRunListener publisher = (SpringApplicationRunListener)constructor.newInstance(springApplication, args);
        //发布事件
        DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
        publisher.starting(bootstrapContext);//spring boot 开始启动
        publisher.environmentPrepared(bootstrapContext,new StandardEnvironment());//环境信息准备完成后
        GenericApplicationContext context = new GenericApplicationContext();
        publisher.contextPrepared(context);//spring容器创建 初始化之后
        publisher.contextLoaded(context);//spring bean definition 加载完成后
        context.refresh();//调用各种bean工厂的后处理器 准备各种bean的后处理器 初始化各种单例
        publisher.started(context);//容器初始化完成（refresh方法调用完毕）
        publisher.running(context);//spring boot 启动完毕

        publisher.failed(context,new Exception("出错了。。。"));//spring boot 启动出错



    }
}
